home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
progjour
/
1989
/
03a
/
cut.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-04-19
|
7KB
|
333 lines
/*
* cut.c - a unix like filter
*
* Author: M. Steven Baker
* Last Revision: October 17, 1988
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#ifndef FILENAME_MAX
#define FILENAME_MAX 68
#endif
FILE *infp;
FILE *outfp = stdout; /* our file pointers */
char infile[FILENAME_MAX] = ""; /* our file names */
char outfile[FILENAME_MAX] = "";
int verbose = 0;
int errflag = 0;
char delim = '\t'; /* default delimiter character */
int fieldflag = 0; /* logical flag for field delimited cut */
int colflag = 0; /* logical flag fro column oriented cut */
int sflag = 0; /* the cut -s flag -- not implemented yet */
char *pgm = "cut"; /* our program name */
#define MAXLINE 8192
char map[MAXLINE+2]; /* our field map array */
char line [MAXLINE+2]; /* our fgets() line buffer */
void usage();
char *help_msg[] = {
"CUT various columns or fields from an ascii text file.",
"The following options may be used singly or in combination:",
"-c columns \t cut columns (ie 1,2,5,7-20)",
"-d delimiter \t field delimiter character (default = tab)",
"-f fields \t cut fields (ie 1,2,5,12-30)",
"-o filename\t create output text file (default stdout)",
/* "-s \t\t don't copy lines without delimiters" , */
"-v\t\t verbose mode"
};
main(argc,argv)
int argc;
char **argv;
{
int ch; /* variable for getopt */
int i;
extern int getopt();
extern char *optarg;
extern int optind, opterr;
for (i = 0; i < MAXLINE; i++) map[i] = 0; /* zero map array */
/* process command-line arguments */
opterr = 0; /* first turn off error messages from getopt */
while ((ch = getopt(argc,argv, "vsc:d:f:o:")) != EOF)
{
switch (ch) {
case 'c':
colflag = 1;
if (setfields(optarg) == EOF) {
errflag++;
if (verbose)
fprintf(stderr,"%s: Error setting columns to cut\n",pgm);
}
break;
case 'd':
delim = *optarg;
break;
case 'f':
fieldflag = 1;
if (setfields(optarg) == EOF) {
errflag++;
if (verbose)
fprintf(stderr,"%s: Error setting fields to cut\n",pgm);
}
break;
case 'v':
verbose = 1;
break;
case 'o': /* output specifed cut text file */
strcpy(outfile, optarg);
outfp = NULL;
break;
case 's': /* not implemented */
sflag = 1;
break;
default: /* unknown option */
errflag++;
break;
}
}
if (colflag && fieldflag) errflag++; /* can't have both options */
if (errflag || !(argc-optind) ) {
usage(pgm);
exit(1);
}
if ( dofiles(argc - optind, argv += optind) ) /* did we have errors? */
exit (1);
exit(0);
}
/*
* dofiles - process each filename or standard input
*/
int dofiles(ac, av)
int ac;
char **av;
{
int ch, errcount = 0;
char *p;
for (; ac > 0; --ac, ++av) {
p = *av;
strcpy(infile,p); /* store binary data filename */
if ((infp = fopen (infile,"rt")) == NULL) {
fprintf(stderr,"%s: ERROR opening input file: %s\n",
pgm,infile);
continue;
}
if (outfp != stdout) {
if ((outfp = fopen (outfile,"wt")) == NULL) {
fprintf(stderr,"%s: ERROR opening output file: %s\n",pgm,outfile);
fclose (infp);
continue;
}
}
if (cut(infp,outfp)== EOF) {
fprintf(stderr,"%s: Error converting file: %s\n",pgm,infile);
fclose(infp);
fclose(outfp);
errcount++;
continue;
}
fclose(infp);
if (fclose(outfp) == EOF) {
fprintf(stderr,"%s: Error closing output file: %s\n",pgm,outfile);
errcount++;
continue;
}
} /* end of for loop */
return (errcount);
}
/*
* do the actual cut
*/
cut(fp1,fp2)
FILE *fp1, *fp2;
{
int i;
char c;
char *p;
while ((p = fgets(line, MAXLINE+2, fp1)) != NULL) {
i = 0;
for (c = *p; *p; c = *++p) {
if (fieldflag) {
if (map[i] || c == '\n') fputc(c,fp2);
if (c == delim) i++;
}
else {
if (colflag) {
if (map[i++] || c == '\n') fputc(c,fp2);
}
else fputc(c,fp2);
}
}
}
return (0);
}
#define BEGIN 0
#define NUMBER 1
#define COMMA 2
#define RANGE 3
/*
* setfields - set fields to cut from command line
*/
int setfields(optarg)
char *optarg;
{
int i, last, state;
char c;
char *p;
i = last = state = BEGIN;
p = optarg;
if ((c =*p) == '\0') return (EOF);
while ((c = *p) && i < MAXLINE) {
switch (state) {
case BEGIN:
i =stoi(&p); /* now pointing to next char */
if (i > 0 && i < MAXLINE) {
last = i;
map[i-1] =1;
state = NUMBER;
}
else return (EOF);
break;
case NUMBER: /* a number was last */
if ( c == '-')
state = RANGE;
else {
if (c == ',') state = COMMA;
else return (EOF);
}
p++; /* increment pointer */
break;
case COMMA:
if (isdigit(c)) {
i = stoi(&p); /* stoi increments pointer */
if (i > 0 && i < MAXLINE) {
last = i;
map[i-1] = 1;
state = NUMBER;
}
else return (EOF);
}
else return (EOF);
break;
case RANGE:
if (isdigit(c)) {
i = stoi(&p); /* stoi increments pointer */
if (i > 0 && i < MAXLINE) {
if (last < i) {
while (last < i)
map[++last -1] = 1;
state = NUMBER;
}
else return (EOF);
}
else return (EOF);
}
else return (EOF);
break;
default:
return (EOF);
}
}
return (0);
}
/* STOI.C More powerful version of atoi.
*
* chopped from the Allen Holub stoi(c)
*
*/
int stoi(instr)
char **instr;
{
/* Convert string to integer. If string starts with 0x it is
* interpreted as a hex number, else if it starts with a 0 it
* is octal, else it is decimal. Conversion stops on encountering
* the first character which is not a digit in the indicated
* radix. *instr is updated to point past the end of the number.
* patched to ignore leading '-' sign, since we need this for range
*/
int num = 0 ;
char *str = *instr;
while( isspace(*str) )
str++ ;
if(*str == '0') {
++str;
if (*str == 'x' || *str == 'X') {
str++;
while( ('0'<= *str && *str <= '9') ||
('a'<= *str && *str <= 'f') ||
('A'<= *str && *str <= 'F') )
{
num *= 16;
num += ('0'<= *str && *str <= '9') ?
*str - '0' :
toupper(*str) - 'A' + 10 ;
str++;
}
}
else {
while( '0' <= *str && *str <= '7' ) {
num *= 8;
num += *str++ - '0' ;
}
}
}
else {
while( '0' <= *str && *str <= '9' ) {
num *= 10;
num += *str++ - '0' ;
}
}
*instr = str;
return( num );
}
/*
* usage - display an abbreviated help usage message
*/
void usage(pname)
char *pname;
{
int i, n = sizeof(help_msg)/sizeof (char *);
fprintf(stderr,"Usage: %s [options] file...\n\n",pname);
for (i = 0; i < n; ++i)
fprintf(stderr, "%s\n",help_msg[i]);
return;
}